#include "timer_queue.h"
#include <Windows.h>
#include <assert.h>
#include "event_loop.h"
#include <time.h>

el::TimerQueue::TimerQueue(EventLoop* loop)
	: loop_(loop)
{

}

el::TimerQueue::~TimerQueue()
{
	for (MultiMapIter iter = map_.begin(); iter != map_.end(); iter++)
	{
		delete iter->second;
	}
}

void el::TimerQueue::handleRead()
{
	assert(loop_->isInLoopThread());
	TTime now = GetTickCount();
	while (!tick_queue_.empty()) 
	{
		TTime expiration = tick_queue_.top();
		if (now < expiration) break;

		tick_queue_.pop();
		std::pair<MultiMapIter, MultiMapIter> pair = map_.equal_range(expiration);
		Timer* timer = NULL;
		while (pair.first != pair.second)
		{
			timer = pair.first->second;
			timer->run();
			pair.first = map_.erase(pair.first);
			if (timer->repeat())
			{
				timer->restart(now);
				tick_queue_.push(timer->expiration());
				map_.insert(std::pair<TTime, Timer*>(timer->expiration(), timer));
			}
			else
			{
				delete timer;
			}
		}
	}
}

void el::TimerQueue::addTimer(const Functor& cb, TTime when, TTime interval)
{
	MutexLockGuard lock(mutex_);
	Timer* timer = new Timer(cb, when, interval);
	loop_->runInLoop(Function<void(void)>(this, &TimerQueue::addTimerInLoop, timer));
}

void el::TimerQueue::addTimerInLoop(Timer* timer)
{
	assert(loop_->isInLoopThread());
	tick_queue_.push(timer->expiration());
	map_.insert(std::pair<TTime, Timer*>(timer->expiration(), timer));
}

el::TTime el::TimerQueue::now()
{
	return GetTickCount();
}
